#include "demo.h"
#include "codeports.h"

typedef struct
{
	BOX box;
	float s;
} Plasma;

void
DEMO_Init(DEMO *demo, BOX *box)
{
	Plasma *plasma;
	demo->box = box;
	demo->data = malloc(sizeof(Plasma));
	plasma = demo->data;
	BOX_Allocate(&plasma->box, box->info.width, box->info.height);
	plasma->s = (rand() % 5 + 1);
	if(demo->box->info.bpp == 1)
	{
		float x, y, c;
		for(x = 0; x < plasma->box.info.width; x += 1.0f)
		{
			for(y = 0; y < plasma->box.info.height; y += 1.0f)
			{
				//c = 128.0f + (128.0f * sinf(x / 2.0f)) + 128.0f + (128.0f * sinf(y / 2.0f)) / 2.0f;
				c = 128.0f + (128.0f * sinf(x / 8.0f)) + 128.0f + (128.0f * sinf(y / 4.0f)) + 128.0f + (128.0f * sinf((x + y) / 8.0f)) + 128.0f + (128.0f * sinf(sqrt(x * x + y * y) / 4.0f)) / 4.0f;
				BOX_SetPixelColor(&plasma->box, x, y, c);
			}
		}
	}
}

#define dist(a, b, c, d) sqrtf((a - c) * (a - c) + (b - d) * (b - d))

void
DEMO_Frame(DEMO *demo)
{
	Plasma *plasma = demo->data;
	float x, y, c;
	plasma->s += (rand() % 5 + 1) * 0.5f;
	for(x = 0; x < plasma->box.info.width; x += 1.0f)
	{
		for(y = 0; y < plasma->box.info.height; y += 1.0f)
		{
			switch(demo->box->info.bpp)
			{
				case 1:
					c = (unsigned int) (plasma->box.buffer[(unsigned int) (y * plasma->box.info.width + x)] + plasma->s) % 256;
					BOX_SetPixelColor(&plasma->box, x, y, c);
					BOX_SetPixelColor(demo->box, x, y, c);
					break;
				case 2:
				case 3:
				case 4:
					c = (4.0f + (sinf(dist(x + plasma->s, y, 128.0f, 128.0f) / 8.0f) + sinf(dist(x, y, 64.0f, 64.0f) / 8.0f) + sinf(dist(x, y + plasma->s / 8.0f, 192.0f, 64) / 8.0f) + sinf(dist(x, y, 192.0f, 100.0f) / 8.0f))) * 32.0f;
					BOX_SetPixelRGB(&plasma->box, x, y, c / 2, c * 2, 255 - c);
					BOX_SetPixelRGB(demo->box, x, y, c / 2, c * 2, 255 - c);
					break;
			}
		}
	}
}

void
DEMO_Final(DEMO *demo)
{
	Plasma *plasma = demo->data;
	BOX_Free(&plasma->box);
	free(demo->data);
}
